home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / emacs_src_18_58.lha / emacs-18.58 / src / dispnew.c < prev    next >
C/C++ Source or Header  |  1992-06-18  |  48KB  |  1,731 lines

  1. /* Newly written part of redisplay code.
  2.    Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include <signal.h>
  22.  
  23. #include "config.h"
  24. #include <stdio.h>
  25. #include <errno.h>
  26.  
  27. #ifdef HAVE_TIMEVAL
  28. #ifdef HPUX
  29. #include <time.h>
  30. #else
  31. #include <sys/time.h>
  32. #endif
  33. #endif
  34.  
  35. #ifdef HAVE_TERMIO
  36. #include <termio.h>
  37. #ifdef TCOUTQ
  38. #undef TIOCOUTQ
  39. #define TIOCOUTQ TCOUTQ
  40. #include <fcntl.h>
  41. #endif /* TCOUTQ defined */
  42. #else
  43. #ifndef VMS
  44. #include <sys/ioctl.h>
  45. #endif /* not VMS */
  46. #endif /* not HAVE_TERMIO */
  47.  
  48. /* Allow m- file to inhibit use of FIONREAD.  */
  49. #ifdef BROKEN_FIONREAD
  50. #undef FIONREAD
  51. #endif
  52.  
  53. /* We are unable to use interrupts if FIONREAD is not available,
  54.    so flush SIGIO so we won't try. */
  55. #ifndef FIONREAD
  56. #ifdef SIGIO
  57. #undef SIGIO
  58. #endif
  59. #endif
  60.  
  61. #undef NULL
  62.  
  63. #include "termchar.h"
  64. #include "termopts.h"
  65. #include "cm.h"
  66. #include "dispextern.h"
  67. #include "lisp.h"
  68. #include "buffer.h"
  69. #include "window.h"
  70. #include "commands.h"
  71.  
  72. #define max(a, b) ((a) > (b) ? (a) : (b))
  73. #define min(a, b) ((a) < (b) ? (a) : (b))
  74.  
  75. #ifndef PENDING_OUTPUT_COUNT
  76. /* Get number of chars of output now in the buffer of a stdio stream.
  77.    This ought to be built in in stdio, but it isn't.
  78.    Some s- files override this because their stdio internals differ.  */
  79. #ifdef __GNU_LIBRARY__
  80. #define    PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
  81. #else
  82. #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
  83. #endif
  84. #endif /* No PENDING_OUTPUT_COUNT */
  85.  
  86. /* Nonzero means do not assume anything about current
  87.    contents of actual terminal screen */
  88.  
  89. int screen_garbaged;
  90.  
  91. /* Desired terminal cursor position (to show position of point),
  92.    origin zero */
  93.  
  94. int cursor_hpos, cursor_vpos;
  95.  
  96. /* Nonzero means last display completed and cursor is really at
  97.    cursor_hpos, cursor_vpos.  Zero means it was preempted. */
  98.  
  99. int display_completed;
  100.  
  101. /* Lisp variable visible-bell; enables use of screen-flash
  102.    instead of audible bell.  */
  103.  
  104. int visible_bell;
  105.  
  106. /* Invert the color of the whole screen, at a low level.  */
  107.  
  108. int inverse_video;
  109.  
  110. /* Line speed of the terminal.  */
  111.  
  112. int baud_rate;
  113.  
  114. /* nil or a symbol naming the window system
  115.    under which emacs is running
  116.    ('x is the only current possibility).  */
  117.  
  118. Lisp_Object Vwindow_system;
  119.  
  120. /* Version number of window system, or nil if no window system.  */
  121.  
  122. Lisp_Object Vwindow_system_version;
  123.  
  124. /* Nonzero means reading single-character input with prompt
  125.    so put cursor on minibuffer after the prompt.  */
  126.  
  127. int cursor_in_echo_area;
  128.  
  129. /* Nonzero means finish redisplay regardless of available input.
  130.    This is used with X windows to avoid a weird timing-dependent bug.  */
  131.  
  132. int force_redisplay;
  133.  
  134. /* Description of actual screen contents.  */
  135.  
  136. struct matrix *current_screen;
  137.  
  138. /* Description of desired screen contents.  */
  139.  
  140. struct matrix *new_screen;
  141.  
  142. /* Buffer sometimes used to hold partial screen contents.  */
  143.  
  144. struct matrix *temp_screen;
  145.  
  146. /* Stdio stream being used for copy of all terminal output.  */
  147.  
  148. FILE *termscript;
  149.  
  150. /* Structure for info on cursor positioning */
  151.  
  152. struct cm Wcm;
  153.  
  154. int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */
  155. int delayed_screen_height;  /* Remembered new screen height.  */
  156. int delayed_screen_width;   /* Remembered new screen width.  */
  157.  
  158. /* This buffer records the history of display preemption.  */
  159.  
  160. struct preempt
  161. {
  162.   /* Number of keyboard characters read so far at preempt.  */
  163.   int keyboard_char_count;
  164.   /* Vertical position at which preemption occurred.  */
  165.   int vpos;
  166. };
  167.  
  168. #define N_PREEMPTIONS 50
  169.  
  170. /* Circular buffer recording recent display preemptions.  */
  171. struct preempt preemptions[N_PREEMPTIONS];
  172.  
  173. /* Index of next element in preemptions.  */
  174. int preemption_index;
  175.  
  176. /* Set these variables in the debugger to force a display preemption.  */
  177. int debug_preemption_vpos = -1;
  178. int debug_preemption_char_count = -1;
  179.  
  180. extern int num_input_chars;
  181.  
  182. /* Free and reallocate current_screen and new_screen.  */
  183.  
  184. struct matrix *make_screen_structure ();
  185.  
  186. remake_screen_structures ()
  187. {
  188.   int i;
  189.  
  190.   if (current_screen)
  191.     free_screen_structure (current_screen);
  192.   if (new_screen)
  193.     free_screen_structure (new_screen);
  194.   if (temp_screen)
  195.     free_screen_structure (temp_screen);
  196.  
  197.   current_screen = make_screen_structure (0);
  198.   new_screen = make_screen_structure (0);
  199.   temp_screen = make_screen_structure (1);
  200.  
  201.   if (message_buf)
  202.     message_buf = (char *) xrealloc (message_buf, screen_width + 1);
  203.   else
  204.     message_buf = (char *) xmalloc (screen_width + 1);
  205.  
  206.   /* This may fix a problem of occasionally displaying garbage in the echo area
  207.      after a resize in X Windows.  */
  208.   for (i = 0; i < screen_width; i++)
  209.     message_buf[i] = ' ';
  210.   message_buf[screen_width] = 0;
  211. }
  212.  
  213. struct matrix *
  214. make_screen_structure (empty)
  215.      int empty;
  216. {
  217.   int i;
  218.   struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix));
  219.  
  220.   new->height = screen_height;
  221.   new->width = screen_width;
  222.   new->highlight = (char *) xmalloc (screen_height);
  223.   new->enable = (char *) xmalloc (screen_height);
  224.   new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *));
  225.   new->used = (int *) xmalloc (screen_height * sizeof (int));
  226.   if (empty)
  227.     {
  228.       /* Make the buffer used by decode_mode_spec.  */
  229.       new->total_contents = (unsigned char *) xmalloc (screen_width + 2);
  230.       for (i = 0; i < screen_width; i++)
  231.     new->total_contents[i] = ' ';
  232.       new->total_contents[screen_width] = 0;
  233.     }
  234.   else
  235.     {
  236.       /* Add 2 to leave extra bytes at beginning and end of each line.  */ 
  237.       new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2));
  238.       for (i = 0; i < screen_height; i++)
  239.     {
  240.       int j;
  241.  
  242.       new->contents[i] = new->total_contents + i * (screen_width + 2) + 1;
  243.       new->contents[i][screen_width] = 0;
  244.       new->contents[i][-1] = 0;
  245.       for (j = 0; j < screen_width; j++)
  246.         new->contents[i][j] = ' ';
  247.     }
  248.     }
  249.   bzero (new->enable, screen_height);
  250.   return new;
  251. }
  252.  
  253. free_screen_structure (matrix)
  254.      struct matrix *matrix;
  255. {
  256.   if (matrix->total_contents)
  257.     free (matrix->total_contents);
  258.   free (matrix->contents);
  259.   free (matrix->highlight);
  260.   free (matrix->enable);
  261.   free (matrix->used);
  262.   free (matrix);
  263. }
  264.  
  265. /* Return the hash code of contents of line VPOS of screen-matrix M.  */
  266.  
  267. int
  268. line_hash_code (m, vpos)
  269.      struct matrix *m;
  270.      int vpos;
  271. {
  272.   register unsigned char *body;
  273.   register int h = 0;
  274.   /* Give all lighlighted lines the same hash code
  275.      so as to encourage scrolling to leave them in place.  */
  276.   if (m->highlight[vpos])
  277.     return -1;
  278.  
  279.   body = m->contents[vpos];
  280.  
  281.   if (must_write_spaces)
  282.     {
  283.       while (1)
  284.     {
  285.       int c = *body++;
  286.       if (c == 0)
  287.         break;
  288.       h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' ';
  289.     }
  290.     }
  291.   else
  292.     {
  293.       while (1)
  294.     {
  295.       int c = *body++;
  296.       if (c == 0)
  297.         break;
  298.       h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c;
  299.     }
  300.     }
  301.   if (h)
  302.     return h;
  303.   return 1;
  304. }
  305.  
  306. /* Return number of characters in line in M at vpos VPOS,
  307.    except don't count leading and trailing spaces
  308.    unless the terminal requires those to be explicitly output.  */
  309.  
  310. int
  311. line_draw_cost (m, vpos)
  312.      struct matrix *m;
  313.      int vpos;
  314. {
  315.   register unsigned char *body;
  316.   register int i;
  317.  
  318.   if (must_write_spaces)
  319.     return m->used[vpos];
  320.  
  321.   body = m->contents[vpos];
  322.   for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--);
  323.  
  324.   i -= count_blanks (body);
  325.   return max (i, 0);
  326. }
  327.  
  328. /* The functions on this page are the interface from xdisp.c to redisplay.
  329.  
  330.  The only other interface into redisplay is through setting
  331.  cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. */
  332.  
  333. /* cancel_line eliminates any request to display a line at position `vpos' */
  334.  
  335. cancel_line (vpos)
  336.      int vpos;
  337. {
  338.   new_screen->enable[vpos] = 0;
  339. }
  340.  
  341. clear_screen_records ()
  342. {
  343.   int i;
  344.  
  345.   bzero (current_screen->enable, screen_height);
  346. }
  347.  
  348. /* Get ready to display on line `vpos'
  349.    and set it up for outputting starting at `hpos' within it.
  350.    Return the text string where that line is stored.  */
  351.  
  352. unsigned char *
  353. get_display_line (vpos, hpos)
  354.      int vpos;
  355.      register int hpos;
  356. {
  357.   if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos)
  358.     abort ();
  359.   if (! new_screen->enable[vpos])
  360.     {
  361.       new_screen->used[vpos] = 0;
  362.       new_screen->highlight[vpos] = 0;
  363.       new_screen->enable[vpos] = 1;
  364.     }
  365.  
  366.   if (hpos > new_screen->used[vpos])
  367.     {
  368.       unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos];
  369.       unsigned char *end = new_screen->contents[vpos] + hpos;
  370.       new_screen->used[vpos] = hpos;
  371.       while (p != end)
  372.     *p++ = ' ';
  373.     }
  374.  
  375.   return new_screen->contents[vpos];
  376. }
  377.  
  378. /* Scroll lines from vpos `from' up to but not including vpos `end'
  379.  down by `amount' lines (`amount' may be negative).
  380.  Returns nonzero if done, zero if terminal cannot scroll them. */
  381.  
  382. int
  383. scroll_screen_lines (from, end, amount)
  384.      int from, end, amount;
  385. {
  386.   register int i;
  387.  
  388.   if (!line_ins_del_ok)
  389.     return 0;
  390.  
  391.   if (amount == 0)
  392.     return 1;
  393.   if (amount > 0)
  394.     {
  395.       set_terminal_window (end + amount);
  396.       if (!scroll_region_ok)
  397.     ins_del_lines (end, -amount);
  398.       ins_del_lines (from, amount);
  399.       set_terminal_window (0);
  400.  
  401.       rotate_vector (current_screen->contents + from,
  402.              sizeof (char *) * (end + amount - from),
  403.              amount * sizeof (char *));
  404.       safe_bcopy (current_screen->used + from,
  405.           current_screen->used + from + amount,
  406.           (end - from) * sizeof current_screen->used[0]);
  407.       safe_bcopy (current_screen->highlight + from,
  408.           current_screen->highlight + from + amount,
  409.           (end - from) * sizeof current_screen->highlight[0]);
  410.       safe_bcopy (current_screen->enable + from,
  411.           current_screen->enable + from + amount,
  412.           (end - from) * sizeof current_screen->enable[0]);
  413.       /* Mark the lines made empty by scrolling as enabled, empty and
  414.      normal video.  */
  415.       bzero (current_screen->used + from,
  416.          amount * sizeof current_screen->used[0]);
  417.       bzero (current_screen->highlight + from,
  418.          amount * sizeof current_screen->highlight[0]);
  419.       for (i = from; i < from + amount; i++)
  420.     {
  421.       current_screen->contents[i][0] = '\0';
  422.       current_screen->enable[i] = 1;
  423.     }
  424.     }
  425.   if (amount < 0)
  426.     {
  427.       set_terminal_window (end);
  428.       ins_del_lines (from + amount, amount);
  429.       if (!scroll_region_ok)
  430.     ins_del_lines (end + amount, -amount);
  431.       set_terminal_window (0);
  432.  
  433.       rotate_vector (current_screen->contents + from + amount,
  434.              sizeof (char *) * (end - from - amount),
  435.              (end - from) * sizeof (char *));
  436.       safe_bcopy (current_screen->used + from,
  437.           current_screen->used + from + amount,
  438.           (end - from) * sizeof current_screen->used[0]);
  439.       safe_bcopy (current_screen->highlight + from,
  440.           current_screen->highlight + from + amount,
  441.           (end - from) * sizeof current_screen->highlight[0]);
  442.       safe_bcopy (current_screen->enable + from,
  443.           current_screen->enable + from + amount,
  444.           (end - from) * sizeof current_screen->enable[0]);
  445.       /* Mark the lines made empty by scrolling as enabled, empty and
  446.      normal video.  */
  447.       bzero (current_screen->used + end + amount,
  448.          - amount * sizeof current_screen->used[0]);
  449.       bzero (current_screen->highlight + end + amount,
  450.          - amount * sizeof current_screen->highlight[0]);
  451.       for (i = end + amount; i < end; i++)
  452.     {
  453.       current_screen->contents[i][0] = '\0';
  454.       current_screen->enable[i] = 1;
  455.     }
  456.     }
  457.   return 1;
  458. }
  459.  
  460. /* Rotate a vector of SIZE bytes, by DISTANCE bytes.
  461.    DISTANCE may be negative.  */
  462.  
  463. rotate_vector (vector, size, distance)
  464.      char *vector;
  465.      int size;
  466.      int distance;
  467. {
  468.   char *temp = (char *) alloca (size);
  469.  
  470.   if (distance < 0)
  471.     distance += size;
  472.  
  473.   bcopy (vector, temp + distance, size - distance);
  474.   bcopy (vector + size - distance, temp, distance);
  475.   bcopy (temp, vector, size);
  476. }
  477.  
  478. /* Like bcopy except never gets confused by overlap.  */
  479.  
  480. safe_bcopy (from, to, size)
  481.      char *from, *to;
  482.      int size;
  483. {
  484.   register char *endf;
  485.   register char *endt;
  486.  
  487.   if (size == 0)
  488.     return;
  489.   if (from > to)
  490.     {
  491.       /* If destination is lower in memory, we can go from the beginning.  */
  492.       endf = from + size;
  493.       while (from != endf)
  494.     *to++ = *from++;
  495.       return;
  496.     }
  497.  
  498.   /* If destination is higher in memory, we can go backwards from the end.  */
  499.   endf = from + size;
  500.   endt = to + size;
  501.  
  502.   do
  503.     *--endt = *--endf;
  504.   while (endf != from);
  505. }
  506.  
  507. /* After updating a window w that isn't the full screen wide,
  508.  copy all the columns that w does not occupy
  509.  from current_screen to new_screen,
  510.  so that update_screen will not change those columns.  */
  511.  
  512. preserve_other_columns (w)
  513.      struct window *w;
  514. {
  515.   register int vpos;
  516.   int start = XFASTINT (w->left);
  517.   int end = XFASTINT (w->left) + XFASTINT (w->width);
  518.   int bot = XFASTINT (w->top) + XFASTINT (w->height);
  519.  
  520.   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
  521.     {
  522.       if (current_screen->enable[vpos] && new_screen->enable[vpos])
  523.     {
  524.       if (start > 0)
  525.         {
  526.           int len;
  527.  
  528.           bcopy (current_screen->contents[vpos],
  529.              new_screen->contents[vpos], start);
  530.           len = min (start, current_screen->used[vpos]);
  531.           if (new_screen->used[vpos] < len)
  532.         new_screen->used[vpos] = len;
  533.         }
  534.       if (current_screen->used[vpos] > end
  535.           && new_screen->used[vpos] < current_screen->used[vpos])
  536.         {
  537.           while (new_screen->used[vpos] < end)
  538.         new_screen->contents[vpos][new_screen->used[vpos]++] = ' ';
  539.           bcopy (current_screen->contents[vpos] + end,
  540.              new_screen->contents[vpos] + end,
  541.              current_screen->used[vpos] - end);
  542.           new_screen->used[vpos] = current_screen->used[vpos];
  543.         }
  544.     }
  545.     }
  546. }
  547.  
  548. /* On discovering that the redisplay for a window was no good,
  549.  cancel the columns of that window,
  550.  so that when the window is displayed over again
  551.  get_display_line will not complain. */
  552.  
  553. cancel_my_columns (w)
  554.      struct window *w;
  555. {
  556.   register int vpos;
  557.   register int start = XFASTINT (w->left);
  558.   register int bot = XFASTINT (w->top) + XFASTINT (w->height);
  559.  
  560.   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
  561.     if (new_screen->enable[vpos] && new_screen->used[vpos] >= start)
  562.       new_screen->used[vpos] = start;
  563. }
  564.  
  565. /* These functions try to perform directly and immediately on the screen
  566.    the necessary output for one change in the buffer.
  567.    They may return 0 meaning nothing was done if anything is difficult,
  568.    or 1 meaning the output was performed properly.
  569.    They assume that the screen was up to date before the buffer
  570.    change being displayed.  THey make various other assumptions too;
  571.    see command_loop_1 where these are called.  */
  572.  
  573. int
  574. direct_output_for_insert (c)
  575.      int c;
  576. {
  577. #ifndef COMPILER_REGISTER_BUG
  578.   register
  579. #endif COMPILER_REGISTER_BUG
  580.     struct window *w = XWINDOW (selected_window);
  581. #ifndef COMPILER_REGISTER_BUG
  582.   register
  583. #endif COMPILER_REGISTER_BUG
  584.     int hpos = cursor_hpos;
  585. #ifndef COMPILER_REGISTER_BUG
  586.   register
  587. #endif COMPILER_REGISTER_BUG
  588.     int vpos = cursor_vpos;
  589.  
  590.   /* Give up if about to continue line */
  591.   if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
  592.  
  593.   /* Avoid losing if cursor is in invisible text off left margin */
  594.       || XINT (w->hscroll) && hpos == XFASTINT (w->left)
  595.     
  596.   /* Give up if cursor outside window (in minibuf, probably) */
  597.       || cursor_vpos < XFASTINT (w->top)
  598.       || cursor_vpos >= XFASTINT (w->top) + XFASTINT (w->height)
  599.  
  600.   /* Give up if cursor not really at cursor_hpos, cursor_vpos */
  601.       || !display_completed
  602.  
  603.   /* Give up if w is minibuffer and a message is being displayed there */
  604.       || EQ (selected_window, minibuf_window) && echo_area_contents)
  605.     return 0;
  606.  
  607.   current_screen->contents[vpos][hpos] = c;
  608.   unchanged_modified = MODIFF;
  609.   beg_unchanged = GPT - BEG;
  610.   XFASTINT (w->last_point) = point;
  611.   XFASTINT (w->last_point_x) = cursor_hpos;
  612.   XFASTINT (w->last_modified) = MODIFF;
  613.  
  614.   reassert_line_highlight (0, cursor_vpos);
  615.   output_chars (¤t_screen->contents[vpos][hpos], 1);
  616.   fflush (stdout);
  617.   ++cursor_hpos;
  618.   if (hpos == current_screen->used[vpos])
  619.     {
  620.       current_screen->used[vpos] = hpos + 1;
  621.       current_screen->contents[vpos][hpos + 1] = 0;
  622.     }
  623.   return 1;
  624. }
  625.  
  626. int
  627. direct_output_forward_char (n)
  628.      int n;
  629. {
  630.   register struct window *w = XWINDOW (selected_window);
  631.  
  632.   /* Avoid losing if cursor is in invisible text off left margin */
  633.   if (XINT (w->hscroll) && cursor_hpos == XFASTINT (w->left))
  634.     return 0;
  635.  
  636.   cursor_hpos += n;
  637.   XFASTINT (w->last_point_x) = cursor_hpos;
  638.   XFASTINT (w->last_point) = point;
  639.   move_cursor (cursor_vpos, cursor_hpos);
  640.   fflush (stdout);
  641.   return 1;
  642. }
  643.  
  644. /* Update the actual terminal screen based on the data in new_screen.
  645.    Value is nonzero if redisplay stopped due to pending input.
  646.    FORCE nonzero means do not stop for pending input.  */
  647.  
  648. update_screen (force, inhibit_hairy_id)
  649.      int force;
  650.      int inhibit_hairy_id;
  651. {
  652.   register struct display_line **p;
  653.   register struct display_line *l, *lnew;
  654.   register int i;
  655.   int pause;
  656.   int preempt_count = baud_rate / 2400 + 1;
  657.   extern input_pending;
  658.  
  659.   start_count(0);
  660.  
  661.   if (screen_height == 0) abort (); /* Some bug zeros some core */
  662.  
  663.   if (force_redisplay)
  664.     force = 1;
  665.  
  666. #ifdef FAST_DISPLAY
  667.   /* Don't compute for i/d line if just want cursor motion. */
  668.   /* Don't allow preemption, etc either */
  669.   for (i = 0; i < screen_height; i++)
  670.     if (new_screen->enable[i])
  671.       break;
  672.  
  673.   if (i >= screen_height)
  674.     {
  675.       update_begin();
  676.       goto update_done;
  677.     }
  678. #endif
  679.  
  680.   if (!force)
  681.     detect_input_pending ();
  682.   if (!force
  683.       && ((num_input_chars == debug_preemption_char_count
  684.        && debug_preemption_vpos == screen_height - 1)
  685.       || input_pending))
  686.     {
  687.       pause = screen_height;
  688.       goto do_pause;
  689.     }
  690.  
  691.   update_begin ();
  692.  
  693.   if (!line_ins_del_ok)
  694.     inhibit_hairy_id = 1;
  695.  
  696. #ifndef FAST_DISPLAY
  697.   /* Don't compute for i/d line if just want cursor motion. */
  698.   for (i = 0; i < screen_height; i++)
  699.     if (new_screen->enable[i])
  700.       break;
  701. #endif
  702.  
  703.   /* Try doing i/d line, if not yet inhibited.  */
  704.   if (!inhibit_hairy_id && i < screen_height)
  705.     force |= scrolling ();
  706.  
  707.   /* Update the individual lines as needed.  Do bottom line first.  */
  708.  
  709.   if (new_screen->enable[screen_height - 1])
  710.     update_line (screen_height - 1);
  711.   for (i = 0; i < screen_height - 1 && (force || !input_pending); i++)
  712.     {
  713.       if (!force && num_input_chars == debug_preemption_char_count
  714.       && debug_preemption_vpos == i)
  715.     break;
  716.       if (new_screen->enable[i])
  717.     {
  718.       /* Flush out every so many lines.
  719.          Also flush out if likely to have more than 1k buffered
  720.          otherwise.   I'm told that telnet connections get really
  721.          screwed by more than 1k output at once.  */
  722.       int outq = PENDING_OUTPUT_COUNT (stdout);
  723.       if (outq > 900
  724.           || (outq > 20 && ((i - 1) % preempt_count == 0)))
  725.         {
  726.           fflush (stdout);
  727.           if (preempt_count == 1)
  728.         {
  729. #ifdef TIOCOUTQ
  730.           if (ioctl (0, TIOCOUTQ, &outq) < 0)
  731.             /* Probably not a tty.  Ignore the error and reset
  732.              * the outq count. */
  733.             outq = PENDING_OUTPUT_COUNT (stdout);
  734. #endif
  735.           outq *= 10;
  736.           sleep (outq / baud_rate);
  737.         }
  738.         }
  739.       if ((i - 1) % preempt_count == 0 && !force)
  740.         detect_input_pending ();
  741.       /* Now update this line.  */
  742.       update_line (i);
  743.     }
  744.     }
  745. #ifdef FAST_DISPLAY
  746. update_done:
  747. #endif
  748.   pause = (i < screen_height - 1) ? i + 1 : 0;
  749.  
  750.   /* Now just clean up termcap drivers and set cursor, etc.  */
  751.   if (!pause)
  752.     {
  753.       if (cursor_in_echo_area < 0)
  754.     move_cursor (screen_height - 1, 0);
  755.       else if (cursor_in_echo_area > 0
  756.            && !current_screen->enable[screen_height - 1])
  757.     move_cursor (screen_height - 1, 0);
  758.       else if (cursor_in_echo_area)
  759.     move_cursor (screen_height - 1,
  760.              min (screen_width - 1,
  761.               current_screen->used[screen_height - 1]));
  762.       else
  763.     move_cursor (cursor_vpos, max (min (cursor_hpos, screen_width - 1), 0));
  764.     }
  765.  
  766.   update_end ();
  767.  
  768.   if (termscript)
  769.     fflush (termscript);
  770.   fflush (stdout);
  771.  
  772.   /* Here if output is preempted because input is detected.  */
  773.  do_pause:
  774.  
  775.   if (screen_height == 0) abort (); /* Some bug zeros some core */
  776.   display_completed = !pause;
  777.   if (pause)
  778.     {
  779.       preemptions[preemption_index].vpos = pause - 1;
  780.       preemptions[preemption_index].keyboard_char_count = num_input_chars;
  781.       preemption_index++;
  782.       if (preemption_index == N_PREEMPTIONS)
  783.     preemption_index = 0;
  784.     }
  785.  
  786.   bzero (new_screen->enable, screen_height);
  787.   stop_count(0);
  788.   return pause;
  789. }
  790.  
  791. /* Called when about to quit, to check for doing so
  792.    at an improper time.  */
  793.  
  794. void
  795. quit_error_check ()
  796. {
  797.   if (new_screen == 0)
  798.     return;
  799.   if (new_screen->enable[0])
  800.     abort ();
  801.   if (new_screen->enable[screen_height - 1])
  802.     abort ();
  803. }
  804.  
  805. /* Decide what insert/delete line to do, and do it */
  806.  
  807. scrolling ()
  808. {
  809.   int unchanged_at_top, unchanged_at_bottom;
  810.   int window_size;
  811.   int changed_lines;
  812.   int *old_hash = (int *) alloca (screen_height * sizeof (int));
  813.   int *new_hash = (int *) alloca (screen_height * sizeof (int));
  814.   int *draw_cost = (int *) alloca (screen_height * sizeof (int));
  815.   register int i;
  816.   int free_at_end_vpos = screen_height;
  817.   
  818.   /* Compute hash codes of all the lines.
  819.      Also calculate number of changed lines,
  820.      number of unchanged lines at the beginning,
  821.      and number of unchanged lines at the end.  */
  822.  
  823.   changed_lines = 0;
  824.   unchanged_at_top = 0;
  825.   unchanged_at_bottom = screen_height;
  826.   for (i = 0; i < screen_height; i++)
  827.     {
  828.       /* Give up on this scrolling if some old lines are not enabled.  */
  829.       if (!current_screen->enable[i])
  830.     return 0;
  831.       old_hash[i] = line_hash_code (current_screen, i);
  832.       if (!new_screen->enable[i])
  833.     new_hash[i] = old_hash[i];
  834.       else
  835.     new_hash[i] = line_hash_code (new_screen, i);
  836.       if (old_hash[i] != new_hash[i])
  837.     {
  838.       changed_lines++;
  839.       unchanged_at_bottom = screen_height - i - 1;
  840.     }
  841.       else if (i == unchanged_at_top)
  842.     unchanged_at_top++;
  843.       /* If line is not changing, its redraw cost is infinite,
  844.      since we can't redraw it.  */
  845.       if (!new_screen->enable[i])
  846.     draw_cost[i] = INFINITY;
  847.       else
  848.     draw_cost[i] = line_draw_cost (new_screen, i);
  849.     }
  850.  
  851.   /* If changed lines are few, don't allow preemption, don't scroll.  */
  852.   if (changed_lines < baud_rate / 2400 || unchanged_at_bottom == screen_height)
  853.     return 1;
  854.  
  855.   window_size = screen_height - unchanged_at_top - unchanged_at_bottom;
  856.  
  857.   if (scroll_region_ok)
  858.     free_at_end_vpos -= unchanged_at_bottom;
  859.   else if (memory_below_screen)
  860.     free_at_end_vpos = -1;
  861.  
  862.   /* If large window, fast terminal and few lines in common between
  863.      current_screen and new_screen, don't bother with i/d calc.  */
  864.   if (window_size >= 18 && baud_rate > 2400
  865.       && (window_size >=
  866.       10 * scrolling_max_lines_saved (unchanged_at_top,
  867.                       screen_height - unchanged_at_bottom,
  868.                       old_hash, new_hash, draw_cost)))
  869.     return 0;
  870.  
  871.   scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
  872.            draw_cost + unchanged_at_top - 1,
  873.            old_hash + unchanged_at_top - 1,
  874.            new_hash + unchanged_at_top - 1,
  875.            free_at_end_vpos - unchanged_at_top);
  876.  
  877.   return 0;
  878. }
  879.  
  880. update_line (vpos)
  881.      int vpos;
  882. {
  883.   register unsigned char *obody, *nbody, *op1, *op2, *np1;
  884.   int tem;
  885.   int osp, nsp, begmatch, endmatch, olen, nlen;
  886.   int save;
  887.   unsigned char *temp;
  888.  
  889.   /* Check for highlighting change.  */
  890.   if (new_screen->highlight[vpos]
  891.       != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
  892.     {
  893.       change_line_highlight (new_screen->highlight[vpos], vpos,
  894.                  (current_screen->enable[vpos]
  895.                   ? current_screen->used[vpos] : 0));
  896.       current_screen->enable[vpos] = 0;
  897.     }
  898.   else
  899.     reassert_line_highlight (new_screen->highlight[vpos], vpos);
  900.  
  901. #ifdef FAST_DISPLAY
  902.   if (current_screen->enable[vpos])
  903.   {
  904.       obody = current_screen->contents[vpos];
  905.       olen = current_screen->used[vpos];
  906.   }
  907.   else olen = 0;
  908.  
  909.   nbody = new_screen->contents[vpos];
  910.   nlen = new_screen->used[vpos];
  911.   
  912.   /* Pretend trailing spaces are not there at all,
  913.      unless for one reason or another we must write all spaces.  */
  914.   /* We know that the previous character byte contains 0.  */
  915.   if (! new_screen->highlight[vpos])
  916.   {
  917.       if (!must_write_spaces)
  918.       while (nbody[nlen - 1] == ' ')
  919.           nlen--;
  920.   }
  921.   else
  922.   {
  923.       /* For an inverse-video line, give it extra trailing spaces
  924.      all the way to the screen edge
  925.      so that the reverse video extends all the way across.  */
  926.       while (nlen < screen_width - 1)
  927.       nbody[nlen++] = ' ';
  928.   }
  929.   
  930.   while (olen > 0 && nlen > 0 && *obody == *nbody)
  931.   {
  932.       olen--; nlen--; obody++; nbody++;
  933.   }
  934.   if (olen > 0 || nlen > 0)
  935.       move_cursor (vpos, nbody - new_screen->contents[vpos]);
  936.   if (nlen > 0) output_chars (nbody, nlen);
  937.   
  938.   if (olen > nlen && new_screen->used[vpos] != screen_width)
  939.       clear_end_of_line(current_screen->used[vpos]);
  940.   /* Exchange contents between current_screen and new_screen.  */
  941.   temp = new_screen->contents[vpos];
  942.   new_screen->contents[vpos] = current_screen->contents[vpos];
  943.   current_screen->contents[vpos] = temp;
  944.   
  945.   /* One way or another, this will enable the line being updated.  */
  946.   current_screen->enable[vpos] = 1;
  947.   current_screen->used[vpos] = new_screen->used[vpos];
  948.   current_screen->highlight[vpos] = new_screen->highlight[vpos];
  949.  
  950. #else /* not FAST_DISPLAY */
  951.  
  952.   /* ??? */
  953.   if (! current_screen->enable[vpos])
  954.     {
  955.       olen = 0;
  956.     }
  957.   else
  958.     {
  959.       obody = current_screen->contents[vpos];
  960.       olen = current_screen->used[vpos];
  961.  
  962.       /* Check for bugs that clobber obody[-1].
  963.      Such bugs might well clobber more than that,
  964.      so we need to find them, not try to ignore them.  */
  965.       if (obody[-1] != 0)
  966.     abort ();
  967.  
  968.       if (! current_screen->highlight[vpos])
  969.     {
  970.       /* Note obody[-1] is always 0.  */
  971.       if (!must_write_spaces)
  972.         while (obody[olen - 1] == ' ')
  973.           olen--;
  974.     }
  975.       else
  976.     {
  977.       /* For an inverse-video line, remember we gave it
  978.          spaces all the way to the screen edge
  979.          so that the reverse video extends all the way across.  */
  980.       while (olen < screen_width - 1)
  981.         obody[olen++] = ' ';
  982.     }
  983.     }
  984.  
  985.   /* One way or another, this will enable the line being updated.  */
  986.   current_screen->enable[vpos] = 1;
  987.   current_screen->used[vpos] = new_screen->used[vpos];
  988. #if !defined (ALLIANT) || defined (ALLIANT_2800)
  989.   current_screen->highlight[vpos] = new_screen->highlight[vpos];
  990. #else
  991.   {
  992.     /* Work around for compiler bug in cc on FX/80 which causes
  993.        "dispnew.c", line 896: compiler error: no table entry for op OREG.  */
  994.     char tmp;
  995.     tmp = new_screen->highlight[vpos];
  996.     current_screen->highlight[vpos] = tmp;
  997.   }
  998. #endif
  999.  
  1000.   if (!new_screen->enable[vpos])
  1001.     {
  1002.       nlen = 0;
  1003.       goto just_erase;
  1004.     }
  1005.  
  1006.   nbody = new_screen->contents[vpos];
  1007.   nlen = new_screen->used[vpos];
  1008.  
  1009.   /* Pretend trailing spaces are not there at all,
  1010.      unless for one reason or another we must write all spaces.  */
  1011.   /* We know that the previous character byte contains 0.  */
  1012.   if (! new_screen->highlight[vpos])
  1013.     {
  1014.       if (!must_write_spaces)
  1015.     while (nlen > 0 && nbody[nlen - 1] == ' ')
  1016.       nlen--;
  1017.       if (nlen == 0)
  1018.     goto just_erase;
  1019.     }
  1020.   else
  1021.     {
  1022.       /* For an inverse-video line, give it extra trailing spaces
  1023.      all the way to the screen edge
  1024.      so that the reverse video extends all the way across.  */
  1025.       while (nlen < screen_width - 1)
  1026.     nbody[nlen++] = ' ';
  1027.     }
  1028.  
  1029.   /* If there's no i/d char, quickly do the best we can without it.  */
  1030.   if (!char_ins_del_ok)
  1031.     {
  1032.       int i,j;
  1033.  
  1034.       for (i = 0; i < nlen; i++)
  1035.     {
  1036.       if (i >= olen || nbody[i] != obody[i])
  1037.         {
  1038.           /* We found a non-matching char.  */
  1039.           move_cursor (vpos, i);
  1040.           for (j = 1; (i + j < nlen &&
  1041.                (i + j >= olen || nbody[i+j] != obody[i+j]));
  1042.            j++);
  1043.           /* Output this run of non-matching chars.  */ 
  1044.           output_chars (nbody + i, j);
  1045.           i += j - 1;
  1046.           /* Now find the next non-match.  */
  1047.         }
  1048.     }
  1049.       /* Clear the rest of the line, or the non-clear part of it.  */
  1050.       if (olen > nlen)
  1051.     {
  1052.       move_cursor (vpos, nlen);
  1053.       clear_end_of_line (olen);
  1054.     }
  1055.  
  1056.       /* Exchange contents between current_screen and new_screen.  */
  1057.       temp = new_screen->contents[vpos];
  1058.       new_screen->contents[vpos] = current_screen->contents[vpos];
  1059.       current_screen->contents[vpos] = temp;
  1060.       return;
  1061.     }
  1062.  
  1063.   if (!olen)
  1064.     {
  1065.       nsp = (must_write_spaces || new_screen->highlight[vpos])
  1066.           ? 0 : count_blanks (nbody);
  1067.       if (nlen > nsp)
  1068.     {
  1069.       move_cursor (vpos, nsp);
  1070.       output_chars (nbody + nsp, nlen - nsp);
  1071.     }
  1072.  
  1073.       /* Exchange contents between current_screen and new_screen.  */
  1074.       temp = new_screen->contents[vpos];
  1075.       new_screen->contents[vpos] = current_screen->contents[vpos];
  1076.       current_screen->contents[vpos] = temp;
  1077.       return;
  1078.     }
  1079.  
  1080.   obody[olen] = 1;
  1081.   save = nbody[nlen];
  1082.   nbody[nlen] = 0;
  1083.  
  1084.   /* Compute number of leading blanks in old and new contents.  */
  1085.   osp = count_blanks (obody);
  1086.   if (!new_screen->highlight[vpos])
  1087.     nsp = count_blanks (nbody);
  1088.   else
  1089.     nsp = 0;
  1090.  
  1091.   /* Compute number of matching chars starting with first nonblank.  */
  1092.   begmatch = count_match (obody + osp, nbody + nsp);
  1093.  
  1094.   /* Spaces in new match implicit space past the end of old.  */
  1095.   /* A bug causing this to be a no-op was fixed in 18.29.  */
  1096.   if (!must_write_spaces && osp + begmatch == olen)
  1097.     {
  1098.       np1 = nbody + nsp;
  1099.       while (np1[begmatch] == ' ')
  1100.     begmatch++;
  1101.     }
  1102.  
  1103.   /* Avoid doing insert/delete char
  1104.      just cause number of leading spaces differs
  1105.      when the following text does not match. */
  1106.   if (begmatch == 0 && osp != nsp)
  1107.     osp = nsp = min (osp, nsp);
  1108.  
  1109.   /* Find matching characters at end of line */
  1110.   op1 = obody + olen;
  1111.   np1 = nbody + nlen;
  1112.   op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
  1113.   while (op1 > op2 && op1[-1] == np1[-1])
  1114.     {
  1115.       op1--;
  1116.       np1--;
  1117.     }
  1118.   endmatch = obody + olen - op1;
  1119.  
  1120.   /* Put correct value back in nbody[nlen].
  1121.      This is important because direct_output_for_insert
  1122.      can write into the line at a later point.  */
  1123.   nbody[nlen] = save;
  1124.   /* Likewise, make sure that the null after the usable space in obody
  1125.      always remains a null.  */
  1126.   obody[olen] = 0;
  1127.  
  1128.   /* tem gets the distance to insert or delete.
  1129.      endmatch is how many characters we save by doing so.
  1130.      Is it worth it?  */
  1131.  
  1132.   tem = (nlen - nsp) - (olen - osp);
  1133.   if (endmatch && tem && endmatch <= DCICcost[tem])
  1134.     endmatch = 0;
  1135.  
  1136.   /* nsp - osp is the distance to insert or delete.
  1137.      begmatch + endmatch is how much we save by doing so.
  1138.      Is it worth it?  */
  1139.  
  1140.   if (begmatch + endmatch > 0 && nsp != osp
  1141.       && begmatch + endmatch <= DCICcost[nsp - osp])
  1142.     {
  1143.       begmatch = 0;
  1144.       endmatch = 0;
  1145.       osp = nsp = min (osp, nsp);
  1146.     }
  1147.  
  1148.   /* Now go through the line, inserting, writing and deleting as appropriate.  */
  1149.  
  1150.   if (osp > nsp)
  1151.     {
  1152.       move_cursor (vpos, nsp);
  1153.       delete_chars (osp - nsp);
  1154.     }
  1155.   else if (nsp > osp)
  1156.     {
  1157.       /* If going to delete chars later in line
  1158.      and insert earlier in the line,
  1159.      must delete first to avoid losing data in the insert */
  1160.       if (endmatch && nlen < olen + nsp - osp)
  1161.     {
  1162.       move_cursor (vpos, nlen - endmatch + osp - nsp);
  1163.       delete_chars (olen + nsp - osp - nlen);
  1164.       olen = nlen - (nsp - osp);
  1165.     }
  1166.       move_cursor (vpos, osp);
  1167.       insert_chars ((char *)0, nsp - osp);
  1168.     }
  1169.   olen += nsp - osp;
  1170.  
  1171.   tem = nsp + begmatch + endmatch;
  1172.   if (nlen != tem || olen != tem)
  1173.     {
  1174.       move_cursor (vpos, nsp + begmatch);
  1175.       if (!endmatch || nlen == olen)
  1176.     {
  1177.       /* If new text being written reaches right margin,
  1178.          there is no need to do clear-to-eol at the end.
  1179.          (and it would not be safe, since cursor is not
  1180.          going to be "at the margin" after the text is done) */
  1181.       if (nlen == screen_width)
  1182.         olen = 0;
  1183.       output_chars (nbody + nsp + begmatch, nlen - tem);
  1184. #ifdef obsolete
  1185. /* the following code loses disastrously if tem == nlen.
  1186.    Rather than trying to fix that case, I am trying the simpler
  1187.    solution found above.  */
  1188.       /* If the text reaches to the right margin,
  1189.          it will lose one way or another (depending on AutoWrap)
  1190.          to clear to end of line after outputting all the text.
  1191.          So pause with one character to go and clear the line then.  */
  1192.       if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
  1193.         {
  1194.           /* endmatch must be zero, and tem must equal nsp + begmatch */
  1195.           output_chars (nbody + tem, nlen - tem - 1);
  1196.           clear_end_of_line (olen);
  1197.           olen = 0;        /* Don't let it be cleared again later */
  1198.           output_chars (nbody + nlen - 1, 1);
  1199.         }
  1200.       else
  1201.         output_chars (nbody + nsp + begmatch, nlen - tem);
  1202. #endif
  1203.     }
  1204.       else if (nlen > olen)
  1205.     {
  1206.       output_chars (nbody + nsp + begmatch, olen - tem);
  1207.       insert_chars (nbody + nsp + begmatch + olen - tem, nlen - olen);
  1208.       olen = nlen;
  1209.     }
  1210.       else if (olen > nlen)
  1211.     {
  1212.       output_chars (nbody + nsp + begmatch, nlen - tem);
  1213.       delete_chars (olen - nlen);
  1214.       olen = nlen;
  1215.     }
  1216.     }
  1217.  
  1218.  just_erase:
  1219.   /* If any unerased characters remain after the new line, erase them.  */
  1220.   if (olen > nlen)
  1221.     {
  1222.       move_cursor (vpos, nlen);
  1223.       clear_end_of_line (olen);
  1224.     }
  1225.   
  1226.   /* Exchange contents between current_screen and new_screen.  */
  1227.   temp = new_screen->contents[vpos];
  1228.   new_screen->contents[vpos] = current_screen->contents[vpos];
  1229.   current_screen->contents[vpos] = temp;
  1230. #endif /* not FAST_DISPLAY */
  1231. }
  1232.  
  1233. count_blanks (str)
  1234.      char *str;
  1235. {
  1236.   register char *p = str;
  1237.   while (*str++ == ' ');
  1238.   return str - p - 1;
  1239. }
  1240.  
  1241. count_match (str1, str2)
  1242.      char *str1, *str2;
  1243. {
  1244.   register char *p1 = str1;
  1245.   register char *p2 = str2;
  1246.   while (*p1++ == *p2++);
  1247.   return p1 - str1 - 1;
  1248. }
  1249.  
  1250. DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
  1251.   1, 1, "FOpen termscript file: ",
  1252.   "Start writing all terminal output to FILE as well as the terminal.\n\
  1253. FILE = nil means just close any termscript file currently open.")
  1254.   (file)
  1255.      Lisp_Object file;
  1256. {
  1257.   if (termscript != 0) fclose (termscript);
  1258.   termscript = 0;
  1259.  
  1260.   if (! NULL (file))
  1261.     {
  1262.       file = Fexpand_file_name (file, Qnil);
  1263.       termscript = fopen (XSTRING (file)->data, "w");
  1264.       if (termscript == 0)
  1265.     report_file_error ("Opening termscript", Fcons (file, Qnil));
  1266.     }
  1267.   return Qnil;
  1268. }
  1269.  
  1270. DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
  1271.   "Tell redisplay that the screen has LINES lines.\n\
  1272. Optional second arg non-nil means that redisplay should use LINES lines\n\
  1273. but that the idea of the actual height of the screen should not be changed.")
  1274.   (n, pretend)
  1275.      Lisp_Object n, pretend;
  1276. {
  1277.   CHECK_NUMBER (n, 0);
  1278.   change_screen_size (XINT (n), 0, !NULL (pretend), 0, 0);
  1279.   return Qnil;
  1280. }
  1281.  
  1282. DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
  1283.   "Tell redisplay that the screen has COLS columns.\n\
  1284. Optional second arg non-nil means that redisplay should use COLS columns\n\
  1285. but that the idea of the actual width of the screen should not be changed.")
  1286.   (n, pretend)
  1287.      Lisp_Object n, pretend;
  1288. {
  1289.   CHECK_NUMBER (n, 0);
  1290.   change_screen_size (0, XINT (n), !NULL (pretend), 0, 0);
  1291.   return Qnil;
  1292. }
  1293.  
  1294. DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
  1295.   "Return number of lines on screen available for display.")
  1296.   ()
  1297. {
  1298.   return make_number (screen_height);
  1299. }
  1300.  
  1301. DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
  1302.   "Return number of columns on screen available for display.")
  1303.   ()
  1304. {
  1305.   return make_number (screen_width);
  1306. }
  1307.  
  1308. #ifdef SIGWINCH
  1309. window_change_signal ()
  1310. {
  1311.   int width, height;
  1312.   extern int errno;
  1313.   int old_errno = errno;
  1314.  
  1315.   get_screen_size (&width, &height);
  1316.   /* Record the new size, but don't reallocate the data structures now.
  1317.      Let that be done later outside of the signal handler.  */
  1318.   change_screen_size (height, width, 0, 1, 0);
  1319.   signal (SIGWINCH, window_change_signal);
  1320.  
  1321.   errno = old_errno;
  1322. }
  1323. #endif /* SIGWINCH */
  1324.  
  1325. /* Do any change in screen size that was requested by a signal.  */
  1326.  
  1327. do_pending_window_change ()
  1328. {
  1329.   /* If change_screen_size should have run before, run it now.  */
  1330.   while (delayed_size_change)
  1331.     {
  1332.       int newwidth = delayed_screen_width;
  1333.       int newheight = delayed_screen_height;
  1334.       delayed_size_change = 0;
  1335.       change_screen_size_1 (newheight, newwidth, 0, 0);
  1336.     }
  1337. }
  1338.  
  1339. /* Change the screen height and/or width.  Values may be given as zero to
  1340.    indicate no change is to take place.
  1341.  
  1342.    PRETEND is normally 0; 1 means change used-size only but don't
  1343.    change the size used for calculations; -1 means don't redisplay.
  1344.  
  1345.    If DELAYED, don't change the screen size now; just record the new
  1346.    size and do the actual change at a more convenient time.  The
  1347.    SIGWINCH handler and the X Windows ConfigureNotify code use this,
  1348.    because they can both be called at inconvenient times.
  1349.  
  1350.    FORCE means finish redisplay now regardless of pending input.
  1351.    This is effective only is DELAYED is not set.  */
  1352.  
  1353. change_screen_size (newlength, newwidth, pretend, delayed, force)
  1354.      register int newlength, newwidth, pretend, delayed, force;
  1355. {
  1356.   /* If we can't deal with the change now, queue it for later.  */
  1357.   if (delayed)
  1358.     {
  1359.       delayed_screen_width = newwidth;
  1360.       delayed_screen_height = newlength;
  1361.       delayed_size_change = 1;
  1362.     }
  1363.   else
  1364.     {
  1365.       delayed_size_change = 0;
  1366.       change_screen_size_1 (newlength, newwidth, pretend, force);
  1367.     }
  1368. }
  1369.  
  1370. change_screen_size_1 (newlength, newwidth, pretend, force)
  1371.      register int newlength, newwidth, pretend, force;
  1372. {
  1373.   if ((newlength == 0 || newlength == screen_height)
  1374.       && (newwidth == 0 || newwidth == screen_width))
  1375.     return;
  1376.   if (newlength && newlength != screen_height)
  1377.     {
  1378.       set_window_height (XWINDOW (minibuf_window)->prev, newlength - 1, 0);
  1379.       XFASTINT (XWINDOW (minibuf_window)->top) = newlength - 1;
  1380.       set_window_height (minibuf_window, 1, 0);
  1381.       screen_height = newlength;
  1382.       if (pretend <= 0)
  1383.     ScreenRows = newlength;
  1384.       set_terminal_window (0);
  1385.     }
  1386.   if (newwidth && newwidth != screen_width)
  1387.     {
  1388.       set_window_width (XWINDOW (minibuf_window)->prev, newwidth, 0);
  1389.       set_window_width (minibuf_window, newwidth, 0);
  1390.       screen_width = newwidth;
  1391.       if (pretend <= 0)
  1392.     ScreenCols = newwidth;
  1393.     }
  1394.   remake_screen_structures ();
  1395.   screen_garbaged = 1;
  1396.   calculate_costs ();
  1397.   force_redisplay += force;
  1398.   if (pretend >= 0)
  1399.     redisplay_preserve_echo_area ();
  1400.   force_redisplay -= force;
  1401. }
  1402.  
  1403. DEFUN ("baud-rate", Fbaud_rate, Sbaud_rate, 0, 0, 0,
  1404.   "Return the output baud rate of the terminal.")
  1405.   ()
  1406. {
  1407.   Lisp_Object temp;
  1408.   XSET (temp, Lisp_Int, baud_rate);
  1409.   return temp;
  1410. }
  1411.  
  1412. DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
  1413.   Ssend_string_to_terminal, 1, 1, 0,
  1414.   "Send STRING to the terminal without alteration.\n\
  1415. Control characters in STRING will have terminal-dependent effects.")
  1416.   (str)
  1417.      Lisp_Object str;
  1418. {
  1419.   CHECK_STRING (str, 0);
  1420.   fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
  1421.   fflush (stdout);
  1422.   if (termscript)
  1423.     {
  1424.       fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
  1425.       fflush (termscript);
  1426.     }
  1427.   return Qnil;
  1428. }
  1429.  
  1430. DEFUN ("ding", Fding, Sding, 0, 1, 0,
  1431.   "Beep, or flash the screen.\n\
  1432. Terminates any keyboard macro currently executing unless an argument\n\
  1433. is given.")
  1434.   (arg)
  1435.   Lisp_Object arg;
  1436. {
  1437.   if (!NULL (arg))
  1438.     {
  1439.       bell ();
  1440.       fflush (stdout);
  1441.     }
  1442.   else
  1443.     bell ();
  1444.   return Qnil;
  1445. }
  1446.  
  1447. bell ()
  1448. {
  1449.   if (noninteractive)
  1450.     putchar (07);
  1451.   else if (!FROM_KBD)  /* Stop executing a keyboard macro. */
  1452.     error ("Keyboard macro terminated by a command ringing the bell");
  1453.   else
  1454.     ring_bell ();
  1455.   fflush (stdout);
  1456. }
  1457.  
  1458. DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 1, 0,
  1459.   "Pause, without updating display, for ARG seconds.")
  1460.   (n)
  1461.      Lisp_Object n;
  1462. {
  1463.   register int t;
  1464. #ifndef subprocesses
  1465. #ifdef HAVE_TIMEVAL
  1466.   struct timeval timeout, end_time, garbage1;
  1467. #endif /* HAVE_TIMEVAL */
  1468. #endif /* no subprocesses */
  1469.  
  1470.   CHECK_NUMBER (n, 0);
  1471.   t = XINT (n);
  1472.   if (t <= 0)
  1473.     return Qnil;
  1474.  
  1475. #ifdef subprocesses
  1476.   wait_reading_process_input (t, 0, 0);
  1477. #else /* No subprocesses */
  1478.   immediate_quit = 1;
  1479.   QUIT;
  1480.  
  1481. #ifdef VMS
  1482.   sys_sleep (t);
  1483. #else /* not VMS */
  1484. /* The reason this is done this way 
  1485.     (rather than defined (H_S) && defined (H_T))
  1486.    is because the VMS preprocessor doesn't grok `defined' */
  1487. #ifdef HAVE_SELECT
  1488. #ifdef HAVE_TIMEVAL
  1489.   gettimeofday (&end_time, &garbage1);
  1490.   end_time.tv_sec += t;
  1491.  
  1492.   while (1)
  1493.     {
  1494.       gettimeofday (&timeout, &garbage1);
  1495.  
  1496.       /* In effect, timeout = end_time - timeout.
  1497.      Break if result would be negative.  */
  1498.       if (timeval_subtract (&timeout, end_time, timeout))
  1499.     break;
  1500.  
  1501.       if (!select (1, 0, 0, 0, &timeout))
  1502.     break;
  1503.     }
  1504. #else /* not HAVE_TIMEVAL */
  1505.   /* Is it safe to quit out of `sleep'?  I'm afraid to trust it.  */
  1506.   sleep (t);
  1507. #endif /* HAVE_TIMEVAL */
  1508. #else /* not HAVE_SELECT */
  1509.   sleep (t);
  1510. #endif /* HAVE_SELECT */
  1511. #endif /* not VMS */
  1512.   
  1513.   immediate_quit = 0;
  1514. #endif /* no subprocesses */
  1515.   return Qnil;
  1516. }
  1517.  
  1518. #ifdef HAVE_TIMEVAL
  1519.  
  1520. /* Subtract the `struct timeval' values X and Y,
  1521.    storing the result in RESULT.
  1522.    Return 1 if the difference is negative, otherwise 0.  */
  1523.  
  1524. int
  1525. timeval_subtract (result, x, y)
  1526.      struct timeval *result, x, y;
  1527. {
  1528.   /* Perform the carry for the later subtraction by updating y.
  1529.      This is safer because on some systems
  1530.      the tv_sec member is unsigned.  */
  1531.   if (x.tv_usec < y.tv_usec)
  1532.     {
  1533.       int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
  1534.       y.tv_usec -= 1000000 * nsec;
  1535.       y.tv_sec += nsec;
  1536.     }
  1537.   if (x.tv_usec - y.tv_usec > 1000000)
  1538.     {
  1539.       int nsec = (y.tv_usec - x.tv_usec) / 1000000;
  1540.       y.tv_usec += 1000000 * nsec;
  1541.       y.tv_sec -= nsec;
  1542.     }
  1543.  
  1544.   /* Compute the time remaining to wait.  tv_usec is certainly positive.  */
  1545.   result->tv_sec = x.tv_sec - y.tv_sec;
  1546.   result->tv_usec = x.tv_usec - y.tv_usec;
  1547.  
  1548.   /* Return indication of whether the result should be considered negative.  */
  1549.   return x.tv_sec < y.tv_sec;
  1550. }
  1551. #endif /* HAVE_TIMEVAL */
  1552.  
  1553. DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 2, 0,
  1554.   "Perform redisplay, then wait for ARG seconds or until input is available.\n\
  1555. Optional second arg non-nil means don't redisplay.\n\
  1556. Redisplay is preempted as always if input arrives, and does not happen\n\
  1557. if input is available before it starts.\n\
  1558. Value is t if waited the full time with no input arriving.")
  1559.   (n, nodisp)
  1560.      Lisp_Object n, nodisp;
  1561. {
  1562. #ifndef subprocesses
  1563. #ifdef HAVE_TIMEVAL
  1564.   struct timeval timeout;
  1565. #else
  1566.   int timeout_sec;
  1567. #endif
  1568.   int waitchannels;
  1569. #endif /* no subprocesses */
  1570.  
  1571.   CHECK_NUMBER (n, 0);
  1572.  
  1573.   if (detect_input_pending ())
  1574.     return Qnil;
  1575.  
  1576.   if (EQ (nodisp, Qnil))
  1577.     redisplay_preserve_echo_area ();
  1578.   if (XINT (n) > 0)
  1579.     {
  1580. #ifdef subprocesses
  1581. #ifdef SIGIO
  1582.       gobble_input ();
  1583. #endif                /* SIGIO */
  1584.       wait_reading_process_input (XINT (n), 1, 1);
  1585. #else                /* no subprocesses */
  1586.       immediate_quit = 1;
  1587.       QUIT;
  1588.  
  1589.       waitchannels = 1;
  1590. #ifdef VMS
  1591.       input_wait_timeout (XINT (n));
  1592. #else                /* not VMS */
  1593. #ifndef HAVE_TIMEVAL
  1594.       timeout_sec = XINT (n);
  1595.       select (1, &waitchannels, 0, 0, &timeout_sec);
  1596. #else                /* HAVE_TIMEVAL */
  1597.       timeout.tv_sec = XINT (n);  
  1598.       timeout.tv_usec = 0;
  1599.       select (1, &waitchannels, 0, 0, &timeout);
  1600. #endif                /* HAVE_TIMEVAL */
  1601. #endif                /* not VMS */
  1602.  
  1603.       immediate_quit = 0;
  1604. #endif                /* no subprocesses */
  1605.     }
  1606.   return detect_input_pending () ? Qnil : Qt;
  1607. }
  1608.  
  1609. char *terminal_type;
  1610.  
  1611. /* Initialization done when Emacs fork is started, before doing stty. */
  1612. /* Determine terminal type and set terminal_driver */
  1613. /* Then invoke its decoding routine to set up variables
  1614.   in the terminal package */
  1615.  
  1616. init_display ()
  1617. {
  1618. #ifdef HAVE_X_WINDOWS
  1619.   extern Lisp_Object Vxterm;
  1620.   Vxterm = Qnil;
  1621. #endif
  1622.  
  1623.   Vwindow_system = Qnil;
  1624.   meta_key = 0;
  1625.   inverse_video = 0;
  1626.   cursor_in_echo_area = 0;
  1627.   terminal_type = (char *) 0;
  1628.  
  1629. #ifdef AMIGA
  1630.   amiga_term_open();
  1631. #endif
  1632.   if (!inhibit_window_system)
  1633.     {
  1634. #ifdef AMIGA
  1635.       amiga_term_init();
  1636.       /* Using Intuition V2.04 */
  1637.       Vwindow_system = intern ("intuition");
  1638.       Vwindow_system_version = make_number (2);
  1639.       goto term_init_done;
  1640. #endif /* AMIGA */
  1641. #ifdef HAVE_X_WINDOWS
  1642.       extern char *alternate_display;
  1643.       char *disp = (char *) egetenv ("DISPLAY");
  1644.  
  1645.       /* Note KSH likes to provide an empty string as an envvar value.  */
  1646.       if (alternate_display || (disp && *disp))
  1647.     {
  1648.       x_term_init ();
  1649.       Vxterm = Qt;
  1650.       Vwindow_system = intern ("x");
  1651. #ifdef X11
  1652.       Vwindow_system_version = make_number (11);
  1653. #else
  1654.       Vwindow_system_version = make_number (10);
  1655. #endif
  1656.       goto term_init_done;
  1657.     }
  1658. #endif /* HAVE_X_WINDOWS */
  1659.       ;
  1660.     }
  1661.   /* Record we aren't using a window system.  */
  1662.   inhibit_window_system = 1;
  1663.  
  1664.   /* Look at the TERM variable */
  1665.   terminal_type = (char *) getenv ("TERM");
  1666.   if (!terminal_type)
  1667.     {
  1668. #ifdef VMS
  1669.       fprintf (stderr, "Please specify your terminal type.\n\
  1670. For types defined in VMS, use  set term /device=TYPE.\n\
  1671. For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
  1672. \(The quotation marks are necessary since terminal types are lower case.)\n");
  1673. #else
  1674.       fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
  1675. #endif
  1676.       exit (1);
  1677.     }
  1678.   term_init (terminal_type);
  1679.  
  1680.  term_init_done:
  1681.   remake_screen_structures ();
  1682.   calculate_costs ();
  1683.  
  1684. #ifdef SIGWINCH
  1685. #ifndef CANNOT_DUMP
  1686.   if (initialized)
  1687. #endif /* CANNOT_DUMP */
  1688.     if (inhibit_window_system)
  1689.       signal (SIGWINCH, window_change_signal);
  1690. #endif /* SIGWINCH */
  1691. }
  1692.  
  1693. syms_of_display ()
  1694. {
  1695.   defsubr (&Sopen_termscript);
  1696.   defsubr (&Sding);
  1697.   defsubr (&Ssit_for);
  1698.   defsubr (&Sscreen_height);
  1699.   defsubr (&Sscreen_width);
  1700.   defsubr (&Sset_screen_height);
  1701.   defsubr (&Sset_screen_width);
  1702.   defsubr (&Ssleep_for);
  1703.   defsubr (&Sbaud_rate);
  1704.   defsubr (&Ssend_string_to_terminal);
  1705.  
  1706.   DEFVAR_BOOL ("inverse-video", &inverse_video,
  1707.     "*Non-nil means use inverse-video.");
  1708.   DEFVAR_BOOL ("visible-bell", &visible_bell,
  1709.     "*Non-nil means try to flash the screen to represent a bell.\n\
  1710. Note: for X windows, you must use x-set-bell instead.");
  1711.   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
  1712.     "*Non-nil means no need to redraw entire screen after suspending.\n\
  1713. It is up to you to set this variable to inform Emacs.");
  1714.   DEFVAR_LISP ("window-system", &Vwindow_system,
  1715.     "A symbol naming the window-system under which Emacs is running,\n\
  1716. \(such as `x'), or nil if emacs is running on an ordinary terminal.");
  1717.   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
  1718.     "Version number of the window system Emacs is running under.");
  1719.   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
  1720.     "Non-nil means put cursor in minibuffer after any message displayed there.");
  1721.  
  1722.   /* Initialize `window-system', unless init_display already decided it.  */
  1723. #ifdef CANNOT_DUMP
  1724.   if (noninteractive)
  1725. #endif
  1726.     {
  1727.       Vwindow_system_version = Qnil;
  1728.       Vwindow_system = Qnil;
  1729.     }
  1730. }
  1731.